package com.nineclock.auth.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.nineclock.auth.entity.IntegrationAuthenticationEntity;
import com.nineclock.auth.processor.AuthenticationProcessor;
import com.nineclock.auth.threadlocal.IntegrationAuthenticationHolder;
import com.nineclock.auth.threadlocal.UserHolder;
import com.nineclock.common.entity.UserInfo;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.JsonUtils;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.dto.SysUserDTO;
import com.nineclock.system.feign.SysUserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    SysUserFeign userFeign;

    @Autowired
    List<AuthenticationProcessor> processors;

    //明文密码为 123456
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //从当前线程获取  认证实体类
        IntegrationAuthenticationEntity entity = IntegrationAuthenticationHolder.get();
        if(entity != null){
            //根据认证类型 选择我们要用的处理器
            AuthenticationProcessor processor = this.chooseAuthenticationProcessor(entity);
            if(processor == null){
                throw new NcException(ResponseEnum.INVALID_USERNAME_PASSWORD);
            }
            //根据选择的处理器 获取userDTO对象
            SysUserDTO userDTO = processor.authenticate(entity);

            //把userDTO中的 用户信息 复制给 userInfo
            UserInfo userInfo = BeanHelper.copyProperties(userDTO, UserInfo.class);

            //判断是pc端的登录请求，还是app端的登录请求
            String clientId = entity.getAuthParameter("client_id");
            userInfo.setClientId(clientId);

            String companyId = entity.getAuthParameter("company_id");
            //如果是pc的登录请求，判断必须是管理员才能登录
            if("pc_client".equalsIgnoreCase(clientId)){
                //第一种： 第一次请求,点击登录，没有企业id， 有用户id
                //第二种： 关联多个企业
                        //第一次请求, 点击登录，没有企业id， 有用户id，
                        //第二次请求，登录进入企业，有企业id， 有用户id
                List<SysCompanyUserDTO> companyUserList = null;
                if(StrUtil.isEmpty(companyId)){
                    companyUserList = userFeign.queryCompanyUser(null, userDTO.getId()).getData();
                }else{
                    companyUserList = userFeign.queryCompanyUser(Long.parseLong(companyId), userDTO.getId()).getData();
                }

                //判断员工是否是管理员
                boolean flag = this.checkAdmin(companyUserList);

                if(!flag){
                    throw new NcException(ResponseEnum.USER_NOT_COMPANY_ADMIN);
                }

                //再次封装userInfo， 把员工和 企业信息封装进去
                wrapper(userInfo , companyUserList.get(0));

            }
            //app端请求
            else{
                if(StrUtil.isEmpty(companyId)){
                    companyId = userDTO.getLastLoginCompanyId() + "";
                }
                List<SysCompanyUserDTO> companyUserList = userFeign.queryCompanyUser(Long.parseLong(companyId), userDTO.getId()).getData();

                if(CollectionUtil.isNotEmpty(companyUserList)){
                    wrapper(userInfo , companyUserList.get(0));
                }
            }


            //把userInfo存储到当前线程
            UserHolder.set(userInfo);
            //创建权限集合（默认 固定权限）
            List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ADMIN");
            grantedAuthorities.add(authority);
            //封装userDetails 并返回
            User user = new User(JsonUtils.toString(userInfo), userDTO.getPassword(), grantedAuthorities);
            return user;
        }
        return null;
    }

    private void wrapper(UserInfo userInfo, SysCompanyUserDTO companyUserDTO) {
        userInfo.setCompanyId(companyUserDTO.getCompanyId());
        userInfo.setCompanyName(companyUserDTO.getCompanyName());
        userInfo.setCompanyUserId(companyUserDTO.getId());
        userInfo.setDepartmentId(companyUserDTO.getDepartmentId());
        userInfo.setDepartmentName(companyUserDTO.getDepartmentName());
        userInfo.setPost(companyUserDTO.getPost());
        userInfo.setWorkNumber(companyUserDTO.getWorkNumber());
        userInfo.setTimeEntry(companyUserDTO.getTimeEntry());
        userInfo.setEnable(true); //是否认证成功
    }

    private boolean checkAdmin(List<SysCompanyUserDTO> companyUserList) {
        if(CollectionUtil.isEmpty(companyUserList)){
            return  false;
        }
        for (SysCompanyUserDTO companyUserDTO : companyUserList) {
            List<SysRoleDTO> roles = companyUserDTO.getRoles();
            for (SysRoleDTO role : roles) {
                if(role.getRoleName().startsWith("ROLE_ADMIN")){
                    return true;
                }
            }
        }

        return false;
    }


    public AuthenticationProcessor chooseAuthenticationProcessor(IntegrationAuthenticationEntity entity){
        String authType = entity.getAuthType();
        if (processors != null && processors.size() > 0){
            for (AuthenticationProcessor processor : processors) {
                if (processor.support(entity)){
                    return processor;
                }

            }
        }

        return null;

    }
}